﻿Imports System.Data.Linq

Public Class CustomerDataManager

    'Step 1. Set up the classes for UniDirectional serialization
    'Step 2. Create your WCF services and use the DataContractSerializer to serialize full object graphs
    'Step 3. Return the LINQ to SQL classes from the services (this auto-detaches the entities)
    'Step 4. Handle update, insert, delete on the DAL by "Attach"-ing the classes back to the DataContext


    Public Shared Function GetCustomerByPhoneNumber(ByVal phone As String) As Customer

        Dim db As New PizzaManiaDataContext

        Dim customer = From cust In db.Customers _
                       Select cust _
                       Where cust.Phone = phone

        Return customer.FirstOrDefault()
    End Function

    ''' <summary>
    ''' Example of calling a stored proc on the DataContext
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Shared Function GetAllCustomers() As IEnumerable(Of Customer)
        Dim db As New PizzaManiaDataContext

        Return db.GetAllCustomers.AsEnumerable() 'Call the stored proc directly
    End Function

    ''' <summary>
    ''' EXAMPLE: Returns all open orders for a given customer. Returns all related collections as well.
    ''' </summary>
    ''' <param name="customerID"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Shared Function GetOpenOrdersByCustomerID(ByVal customerID As Integer) As IEnumerable(Of Order)
        Dim db As New PizzaManiaDataContext
        'We want to also serialize the related collections as well.
        Dim dlo As DataLoadOptions = New DataLoadOptions()
        dlo.LoadWith(Of Order)(Function(o As Order) o.OrderPizzas)
        dlo.LoadWith(Of OrderPizza)(Function(op As OrderPizza) op.OrderPizzaToppings)
        db.LoadOptions = dlo

        Dim orders = From order In db.Orders _
                     Select order _
                     Where order.Customer_ID = customerID AndAlso _
                           order.DeliveredDate Is Nothing


        Return orders.AsEnumerable()
    End Function

    ''' <summary>
    ''' Updates, Inserts or Deletes a single customer
    ''' </summary>
    ''' <param name="cust"></param>
    ''' <param name="isDelete"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Shared Function SaveCustomer(ByRef cust As Customer, ByVal isDelete As Boolean) As Boolean
        Dim db As New PizzaManiaDataContext

        If isDelete AndAlso cust.Customer_ID > 0 Then
            db.Customers.Attach(cust, False)
            db.Customers.DeleteOnSubmit(cust)
        Else
            'Insert, update 
            If cust.Customer_ID < 1 Then
                'insert
                db.Customers.InsertOnSubmit(cust)
            Else
                'update
                db.Customers.Attach(cust, True)
            End If
        End If

        Try
            'Specifies that all updates to the database should be tried, 
            'and that concurrency conflicts should be accumulated and 
            'returned at the end of the process.
            db.SubmitChanges(ConflictMode.ContinueOnConflict)

        Catch ex As ChangeConflictException
            ' Get conflict information, and take actions
            ' that are appropriate for your application.
            ' See MSDN Article "How to: Manage Change
            ' Conflicts (LINQ to SQL).
            Return False
        End Try

        Return True
    End Function

    ''' <summary>
    ''' Updates, inserts and deletes multiple customers in a single database transaction.
    ''' </summary>
    ''' <param name="updated"></param>
    ''' <param name="deleted"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Shared Function SaveCustomers(ByRef updated As IEnumerable(Of Customer), ByVal deleted As IEnumerable(Of Customer))
        Dim hasCustomers = (updated IsNot Nothing AndAlso updated.Count > 0)
        Dim hasDeletedCustomers = (deleted IsNot Nothing AndAlso deleted.Count > 0)


        If (Not hasCustomers) AndAlso (Not hasDeletedCustomers) Then
            Return False 'nothing at all to save
        End If

        Dim db As New PizzaManiaDataContext

        For Each c In updated
            'Insert/update customers
            If c.Customer_ID = 0 Then
                db.Customers.InsertOnSubmit(c)
            Else
                db.Customers.Attach(c, c.IsDirty)
            End If
        Next

        If hasDeletedCustomers Then
            'Delete customers 
            db.Customers.AttachAll(deleted, False)
            db.Customers.DeleteAllOnSubmit(deleted)

        End If

        Try
            'This will continue to process the 
            ' rest of the customers even if one fails.
            'There's one database transaction for all records that are attached.
            'Since we attached all updates/inserts/deletes 
            ' they will all be processed in one transaction.
            db.SubmitChanges(ConflictMode.ContinueOnConflict)

            'Reset the IsDirty flag
            For Each c In updated
                c.IsDirty = False
            Next

        Catch ex As ChangeConflictException
            'TODO: Conflict Handling
            Throw
            Return False
        End Try

        Return True
    End Function

End Class
